/**
 *******************************************************************************
 * @file  iap.c
 * @brief This file provides firmware functions to manage the IAP.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2019-06-26       Yangjp          First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2016, Huada Semiconductor Co., Ltd. All rights reserved.
 *
 * This software is owned and published by:
 * Huada Semiconductor Co., Ltd. ("HDSC").
 *
 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
 *
 * This software contains source code for use with HDSC
 * components. This software is licensed by HDSC to be adapted only
 * for use in systems utilizing HDSC components. HDSC shall not be
 * responsible for misuse or illegal use of this software for devices not
 * supported herein. HDSC is providing this software "AS IS" and will
 * not be responsible for issues arising from incorrect user implementation
 * of the software.
 *
 * Disclaimer:
 * HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
 * REGARDING THE SOFTWARE (INCLUDING ANY ACCOMPANYING WRITTEN MATERIALS),
 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
 * WARRANTY OF NONINFRINGEMENT.
 * HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
 * SAVINGS OR PROFITS,
 * EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
 * FROM, THE SOFTWARE.
 *
 * This software may be replicated in part or whole for the licensed use,
 * with the restriction that this Disclaimer and Copyright notice must be
 * included with each copy of this software, whether used in part or whole,
 * at all times.
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "iap.h"
#include "basic.h"
#include "flash.h"
#include "com.h"
#include "modem.h"

/**
 * @addtogroup HC32_Boot
 * @{
 */

/**
 * @defgroup IAP IAP
 * @{
 */

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
static uint32_t JumpAddress;
static func_ptr_t JumpToApplication;

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @defgroup IAP_Global_Functions IAP Global Functions
 * @{
 */

/**
 * @brief  MCU Peripheral registers write unprotected.
 * @param  None
 * @retval None
 * @note   Comment/uncomment each API depending on APP requires.
 */
static void Peripheral_WE(void)
{
    /* Unlock CLK registers */
    CLK_UNLOCK();
    /* Unlock GPIO register */
    GPIO_UNLOCK();
    /* Unlock all EFM registers */
    EFM_UNLOCK();

#if defined(HC32F160)
    /* Unlock all INTC reginsters */
    INTC_UNLOCK();
#endif

#if defined(HC32F4A0)
    /* Unlock EFM register: FWMC */
    EFM_FWMC_UNLOCK();
    /* Unlock all EFM Sector write protection */
    EFM_SECTOR_UNLOCK();
#endif

#if defined(HC32F460) || defined(HC32F4A0)
    /* Unlock PWC register: FCG0 */
    FCG0_UNLOCK();
    /* Unlock SRAM register: WTCR */
    SRAM_WTCR_UNLOCK();
#endif
}

/**
 * @brief  MCU Peripheral registers write protected.
 * @param  None
 * @retval None
 * @note Comment/uncomment each API depending on APP requires.
 */
static void Peripheral_WP(void)
{
    /* Lock CLK registers */
    CLK_LOCK();
    /* Lock GPIO register */
    GPIO_LOCK();
    /* Lock all EFM registers */
    EFM_LOCK();

#if defined(HC32F160)
    /* Unlock all INTC reginsters */
    INTC_LOCK();
#endif

#if defined(HC32F4A0)
    /* Lock EFM register: FWMC */
    EFM_FWMC_LOCK();
    /* Lock all EFM Sector write protection */
    EFM_SECTOR_LOCK();
#endif

#if defined(HC32F460) || defined(HC32F4A0)
    /* Lock PWC register: FCG0 */
    FCG0_LOCK();
    /* Lock SRAM register: WTCR */
    SRAM_WTCR_LOCK();
#endif
}

/**
 * @brief  Boot reset configure.
 * @param  None
 * @retval None
 */
static void IAP_ResetConfig(void)
{
    /* De-Init Peripheral */
    LED_DeInit();
    COM_DeInit();
    CRC_DeInit();
    SysTick_DeInit();
    SystemClock_DeInit();
    /* Lock Peripheral */
    Peripheral_WP();
}

/**
 * @brief  Jump from boot to app function.
 * @param  [in] u32Addr                 APP address
 * @retval Error                        APP address error
 */
static en_result_t IAP_JumpToApp(uint32_t u32Addr)
{
    uint32_t u32StackTop = *((__IO uint32_t *)u32Addr);

    /* Check if user code is programmed starting from address "u32Addr" */
    /* Check stack top pointer. */
    if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + RAM_SIZE)))
    {
        IAP_ResetConfig();
        /* Jump to user application */
        JumpAddress = *(__IO uint32_t *)(u32Addr + 4U);
        JumpToApplication = (func_ptr_t)JumpAddress;
        /* Initialize user application's Stack Pointer */
        __set_MSP(*(__IO uint32_t *)u32Addr);
#if defined(HC32F460) || defined(HC32F4A0) || defined(HC32M423)       
        /* Rebase the vector table base address */
        SCB->VTOR = ((uint32_t) u32Addr & SCB_VTOR_TBLOFF_Msk);
#endif        
        /* Jump to application Reset Handler in the application */
        JumpToApplication();
    }

    return Error;
}

/**
 * @brief  Initialize IAP
 * @param  None
 * @retval None
 */
void IAP_Init(void)
{
    /* Unlock Peripheral */
    Peripheral_WE();
    /* Init Peripheral */
    SystemClock_Init();
    SysTick_Init();
    LED_Init();
    COM_Init();
    CRC_Init();
}

/**
 * @brief  IAP function.
 * @param  None
 * @retval None
 */
void IAP_Main(void)
{
    en_result_t enRet;
    uint32_t u32AppFlag, u32AppAddr;

    u32AppFlag = *(__IO uint32_t *)APP_UPGRADE_ADDRESS;
    if ((APP_UPGRADE_FLAG != u32AppFlag))
    {
        u32AppFlag = *(__IO uint32_t *)APP_FLAG_ADDRESS;
        if ((APP_FLAG == u32AppFlag))
        {
            u32AppAddr = *(__IO uint32_t *)APP_RUN_ADDRESS;
            if ((u32AppAddr >= (FLASH_BASE + BOOT_SIZE)) && (u32AppAddr < (FLASH_BASE + FLASH_SIZE)))
            {
                if (Error == IAP_JumpToApp(u32AppAddr))
                {
                #if defined(HC32F4A0)
                    LED_ON(LED_G1_PORT, LED_G1_PIN);
                #else
                    LED_ON(LED_R_PORT, LED_R_PIN);
                #endif
                }
            }
        }
    }

    for (;;)
    {
        enRet = Modem_Process(BOOT_WAIT_TIME);
        if (enRet == Ok)
        {
            u32AppAddr = *(__IO uint32_t *)APP_RUN_ADDRESS;
            if (Error == IAP_JumpToApp(u32AppAddr))
            {
            #if defined(HC32F4A0)
                LED_ON(LED_G2_PORT, LED_G2_PIN);
            #else
                LED_ON(LED_B_PORT, LED_B_PIN);
            #endif
            }
        }
        else
        {
        #if defined(HC32F4A0)
            LED_ON(LED_G1_PORT, LED_G1_PIN);
            LED_ON(LED_G2_PORT, LED_G2_PIN);
        #else
            LED_ON(LED_B_PORT, LED_B_PIN);
            LED_ON(LED_R_PORT, LED_R_PIN);
        #endif
        }
    }
}

/**
 * @}
 */

/**
 * @}
 */

/**
* @}
*/

/******************************************************************************
 * EOF (not truncated)
 *****************************************************************************/
